home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 25 / CU Amiga Magazine's Super CD-ROM 25 (1998)(EMAP Images)(GB)(Track 1 of 2)[!][issue 1998-08].iso / CUCD / Magazine / C_Tutorial / Part-13 / PatchLib / source / SetPatchA.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-17  |  19.7 KB  |  598 lines

  1. /*
  2. **    patch.library
  3. **
  4. **    Copyright © 1993-1997 by Stefan Fuchs
  5. **        Freely distributable.
  6. */
  7.  
  8. #ifndef _PATCH_INCLUDES_H
  9. #include "patch_includes.h"
  10. #endif
  11.  
  12.  
  13. APTR FindTaskListObject( struct Patch *, APTR, ULONG);
  14.  
  15. #define LVOMatchPattern -846
  16. #define LVOMatchPatternNoCase -972
  17. #define LVOFindTask -294
  18. #define LVOFreeMem -210
  19. #define LVOAllocMem -198
  20. #define LVOStackSwap -732
  21.  
  22. /****** patch.library/SetPatchA ***************************************
  23. *
  24. *   NAME
  25. *        SetPatchA -- Changes certain attributes of a patch. (V3)
  26. *        SetPatch -- varargs stub for SetPatchA(). (V3)
  27. *
  28. *   SYNOPSIS
  29. *        Error = SetPatchA( patch, taglist )
  30. *        D0                 A0     A1
  31. *
  32. *        ULONG Error SetPatchA( struct Patch *, struct TagItem *);
  33. *
  34. *        Error = SetPatch( patch, ...)
  35. *
  36. *        ULONG Error SetPatch( struct Patch *, ...);
  37. *
  38. *   FUNCTION
  39. *        Changes certain attributes of a patch (see TAGS).
  40. *
  41. *   INPUTS
  42. *        patch = pointer to a patch structure or NULL for no action
  43. *        taglist = pointer to array of tags
  44. *
  45. *   TAGS
  46. *        PATT_CreateTaskList (ULONG) - Create a TaskList of the given type:
  47. *                TL_TYPE_INCLUDE:
  48. *                       all specified tasks will use the patchroutine,
  49. *                       all others will ignore it.
  50. *                       So if no Task is specified via PATT_AddTask... tags,
  51. *                       the patchroutine will be used for NO tasks!
  52. *                TL_TYPE_EXCLUDE:
  53. *                       all specified tasks will ignore the patchroutine,
  54. *                       all others will use it.
  55. *                       So if no Task is specified via PATT_AddTask... tags,
  56. *                       the patchroutine will be used for ALL tasks!
  57. *        PATT_DeleteTaskList (BOOL) - Delete any existing TaskList
  58. *                This will return the patch to its default behaviour, which is
  59. *                to call the patchroutine for any task.
  60. *                It is not required to remove the TaskList, before you remove
  61. *                a patch, (via RemovePatchTags()) because this will
  62. *                automatically be done by patch.library.
  63. *        PATT_AddTaskID (struct Task *) - Add a task address to the patch
  64. *                                         TaskList.
  65. *                Patch.library takes care that one TaskID appears only once
  66. *                in the TaskList.
  67. *                Unlike many tags, you may specify this tag more than once
  68. *                in one taglist to add multiple tasks to the list.
  69. *        PATT_AddTaskName (STRPTR) - Add a task of the given name to
  70. *                                    the patch TaskList.
  71. *                The string will be copied into an internal buffer.
  72. *                Patch.library takes care that one TaskName appears only once
  73. *                in the TaskList.
  74. *                Unlike many tags, you may specify this tag more than once
  75. *                in one taglist to add multiple tasks to the list.
  76. *        PATT_RemTaskID (struct Task *) - Remove a task address from the
  77. *                                         patch TaskList
  78. *                Unlike many tags, you may specify this tag more than once
  79. *                in one taglist to add multiple tasks to the list.
  80. *        PATT_RemTaskName (APTR) - Remove a task of the given name from the
  81. *                                  patch TaskList.
  82. *                Unlike many tags, you may specify this tag more than once
  83. *                in one taglist to add multiple tasks to the list.
  84. *        PATT_Disabled (V4) (BOOL) - Enable (False) or disable (True) a patch.
  85. *                For disabling a patch a nesting counter is provided.
  86. *                In order to restore normal patch execution, the programmer
  87. *                must provide exactly one call to 'enable'
  88. *                for every 'disable'.
  89. *                If a patch is disabled this does not mean, that no task
  90. *                continues to use the patched code. It only makes sure,
  91. *                that no further tasks enter the patch code.
  92. *                If PATT_Disabled,TRUE is set with InstallPatchTags() the
  93. *                patch will not be called until explicitly enabled
  94. *                by a call to SetPatchTags().
  95. *        PATT_AddRemoveHook (V4) (struct Hook *) - Add a Hook, which is called
  96. *                by patch.library whenever a patch is removed from memory.
  97. *                Neither the Hook structure nor the hookfunction are copied
  98. *                into internal memory. So freeing these structures must be
  99. *                accomplished by the hookfunction itself.
  100. *                It must also preserve all registers.
  101. *                The hookobject (Register A2) for this hook is the patch
  102. *                structure.
  103. *                For more information about hooks see utility/hooks.h,
  104. *                utility.library/CallHook() or the RKMs.
  105. *                Unlike many tags, you may specify this tag more than once
  106. *                in one taglist to add multiple tasks to the list.
  107. *        PATT_RemRemoveHook (V4) (struct Hook *) - Remove a Hook installed
  108. *                with PATT_AddRemoveHook.
  109. *                Unlike many tags, you may specify this tag more than once
  110. *                in one taglist to add multiple tasks to the list.
  111. *        PATT_UserData (V5) (ULONG) - Attach userdata to a patch.
  112. *                Use this tag only, if you are the owner (creator) of the
  113. *                patch.
  114. *        PATT_AddTaskPattern (V5) (STRPTR) - Add a pattern of tasknames
  115. *                                            to the patch TaskList.
  116. *                The pattern may contain dos wildcards.
  117. *                Patch.library takes care that one pattern appears only once
  118. *                in the TaskList.
  119. *                Unlike many tags, you may specify this tag more than once
  120. *                in one taglist to add multiple tasks to the list.
  121. *                This tag only works with kickstart V37+.
  122. *                DO NOT USE this tag, if you patch one of the following
  123. *                dos-functions: MatchPattern() or MatchPatternNocase()
  124. *        PATT_RemTaskPattern (V5) (STRPTR) - Remove a taskpattern from the
  125. *                                            patch TaskList.
  126. *                Unlike many tags, you may specify this tag more than once
  127. *                in one taglist to add multiple tasks to the list.
  128. *        PATT_StackSize (V5) (ULONG) - Minimum stacksize (in bytes) your
  129. *                                      function requires.
  130. *                This value should be a multiple of 4 and more than 256.
  131. *                If a taskpattern (see PATT_AddtaskPattern) is active,
  132. *                at least 1500 Bytes should be specified.
  133. *                DO NOT USE this tag, if you patch one of the following
  134. *                exec-functions:
  135. *                FindTask(), AllocMem(), FreeMem() or StackSwap()
  136. *                You may specify zero to turn stack extension off.
  137. *        PATT_Priority (V5) (BYTE) - Priority of the patch
  138. *                valid range: -127...+126
  139. *                It indicates the sequence of patches, if more than
  140. *                one patch for a function is installed.
  141. *                The original code has a priority of 0.
  142. *                Priority:    Meaning:
  143. *                >0: patch will be executed before the original
  144. *                <0: patch will be executed after the original
  145. *                =0: patch will be executed instead of the original (default)
  146. *                Normally only the priorities +5, 0, -5 should be used.
  147. *                Changing the priority of an active patch is a difficult
  148. *                operation. It may fail with PATERR_PatchInUse.
  149. *                You MUST NOT change the priority of a patch in respect
  150. *                to the original function (see above).
  151. *
  152. *   RESULT
  153. *        Error = errorcode as defined in patch.h.
  154. *                PATERR_Ok
  155. *                        Indicates success of the operation.
  156. *                PATERR_OutOfMem
  157. *                        Indicates that there was not enough memory to
  158. *                        complete the operation.
  159. *                PATERR_PatchInUse
  160. *                        Indicates that some other task is using the
  161. *                        installed function and the priority of the patch
  162. *                        can't be changed right now.
  163. *                        Your task may wait and try again later.
  164. *                PATERR_InvalidHandle
  165. *                        Indicates that the pointer to the patch passed
  166. *                        to the function was not or is no longer valid.
  167. *                        This might happen, if you pass a wrong pointer or
  168. *                        you got the pointer via FindPatch() and another
  169. *                        task has removed the patch before this task called
  170. *                        RemovePatchTags().
  171. *                PATERR_NoTaskList
  172. *                        No valid TaskList is attached to the patch.
  173. *                        The SetPatchA() function with the PATT_CreateTaskList
  174. *                        tag specified, must be called to allocate a TaskList.
  175. *                PATERR_TaskListExists
  176. *                        PATT_CreateTaskList was specified, but there already
  177. *                        exists a TaskList.
  178. *                PATERR_InvalidTaskList
  179. *                        PATT_CreateTaskList was specified with a wrong
  180. *                        parameter.
  181. *                PATERR_KickTooOld
  182. *                        PATT_AddTaskPattern was used on a system with
  183. *                        Kickstart V36or lower.
  184. *                        (No longer possible with patch.library V6+, as
  185. *                        Kickstart V37+ is required.)
  186. *                PATERR_InvalidPattern
  187. *                        PATT_AddTaskList was used with a string,
  188. *                        which contained an invalid pattern.
  189. *                        See dos.library ParsePattern() for more informations.
  190. *                PATERR_Restricted
  191. *                        PATT_AddTaskPattern or PATT_StackSize was used for a
  192. *                        forbidden function (see TAGS).
  193. *
  194. *   NOTES
  195. *        Using the TaskList feature provided by this function will
  196. *        (by a huge amount in the case of PATT_AddTaskPattern) increase
  197. *        the stackusage of the patched function.
  198. *        See PATT_StackSize for a solution.
  199. *
  200. *   BUGS
  201. *
  202. *   SEE ALSO
  203. *        InstallPatchTags(), patch.h, patchtags.h,
  204. *        dos.library/ParsePatternNoCase(), dos.library/ParsePattern()
  205. *
  206. ******************************************************************************
  207. *
  208. */
  209.  
  210. ULONG LIBFUNC SetPatchA( REGA0 struct Patch *patch GNUC_REGA0, REGA1 struct TagItem *taglist GNUC_REGA1)
  211. {
  212. ULONG Result = PATERR_Ok;
  213. struct TagItem *tlist;
  214. struct TLHeader *tasklistheader;
  215. struct Node *pointer;
  216. struct MasterPatch *master;
  217. ULONG bufsize;
  218. APTR pattern;
  219.  
  220.     if( patch)
  221.     {
  222.         Result = SAVEObtainSemaphore();
  223.         if (Result == 0L)
  224.         {
  225.             if( patch->PS_Node.ln_Type != PS_TYPE_MASTER)
  226.             {
  227.                 Result = TestPatchHandle(patch);
  228.                 if (Result == 0L)
  229.                 {
  230.  
  231.  
  232.  
  233.                     if( tlist = FindTagItem(PATT_CreateTaskList, taglist))
  234.                     {
  235.                         if((tlist->ti_Data == TL_TYPE_EXCLUDE) || (tlist->ti_Data == TL_TYPE_INCLUDE))
  236.                         {
  237.                             if(patch->PS_PatchCode->PC_TaskList)
  238.                             {
  239.                                 Result = PATERR_TaskListExists;
  240.                             }
  241.                             else
  242.                             {
  243.                                 if( tasklistheader = BAllocmem( sizeof( struct TLHeader), MEMF_CLEAR | MEMF_PUBLIC))
  244.                                 {
  245.                                     NewList( (struct List *)tasklistheader);
  246.                                     tasklistheader->TL_List.lh_Type = tlist->ti_Data;
  247.                                     if (tlist->ti_Data == TL_TYPE_INCLUDE)
  248.                                     {
  249.                                         tasklistheader->TL_Result1 = 0L;
  250.                                         tasklistheader->TL_Result2 = 1L;
  251.                                     }
  252.                                     else
  253.                                     {
  254.                                         tasklistheader->TL_Result1 = 1L;
  255.                                         tasklistheader->TL_Result2 = 0L;
  256.                                     }
  257.                                     patch->PS_PatchCode->PC_TaskList = tasklistheader;
  258.                                 }
  259.                                 else
  260.                                 {
  261.                                     Result = PATERR_OutOfMem;
  262.                                 }
  263.                             }
  264.                         }
  265.                         else Result = PATERR_InvalidTaskList;
  266.                         if( Result != PATERR_Ok) goto Ende;
  267.                     }
  268.  
  269.  
  270.  
  271.                     if( GetTagData(PATT_DeleteTaskList, 0L, taglist))
  272.                     {
  273.                         if(tasklistheader = patch->PS_PatchCode->PC_TaskList)
  274.                         {
  275.                             patch->PS_PatchCode->PC_TaskList = 0L;
  276.                             for (pointer = (struct Node *) tasklistheader->TL_List.lh_Head;
  277.                                  pointer->ln_Succ;
  278.                                  pointer = (struct Node *) tasklistheader->TL_List.lh_Head)
  279.                             {
  280.                                 if( pointer->ln_Type == TLI_TYPE_TASKPATTERN)
  281.                                     AFreemem( ((struct TLNode *)pointer)->TN_Pattern);
  282.                                 ADeleteMyListNode(pointer);
  283.                             }
  284.                             AFreemem(tasklistheader);
  285.                         }
  286.                     }
  287.  
  288.  
  289.  
  290.                     if( tlist = FindTagItem(PATT_Disabled, taglist))
  291.                     {
  292.                         if( tlist->ti_Data)
  293.                         {
  294.                             if( (patch->PS_Flags & PSF_InternalCall) == 0)
  295.                                 patch->PS_PatchCode->PC_Disable++;
  296.                         }
  297.                         else
  298.                         {
  299.                             patch->PS_PatchCode->PC_Disable--;
  300.                         }
  301.                     }
  302.  
  303.  
  304.  
  305.                     tlist = taglist;
  306.                     while( tlist = FindTagItem(PATT_AddTaskID, tlist))
  307.                     {
  308.                         if( patch->PS_PatchCode->PC_TaskList)
  309.                         {
  310.                             if( FindTaskListObject( patch, (APTR)tlist->ti_Data, TLI_TYPE_TASKID) == NULL)
  311.                             {
  312.                                 if( pointer = ACreateMyListNode( (struct List *) patch->PS_PatchCode->PC_TaskList, sizeof( struct Node)))
  313.                                 {
  314.                                     pointer->ln_Name = (STRPTR)tlist->ti_Data;
  315.                                     pointer->ln_Type = TLI_TYPE_TASKID; /* This must be set, if everything else is initialized ok */
  316.                                 }
  317.                                 else
  318.                                 {
  319.                                     Result = PATERR_OutOfMem;
  320.                                     break;
  321.                                 }
  322.                             }
  323.                         }
  324.                         else
  325.                         {
  326.                             Result = PATERR_NoTaskList;
  327.                             break;
  328.                         }
  329.                         tlist++;
  330.                     }
  331.                     if( Result != PATERR_Ok) goto Ende;
  332.  
  333.  
  334.  
  335.                     tlist = taglist;
  336.                     while( tlist = FindTagItem(PATT_AddTaskName, tlist))
  337.                     {
  338.                         if( patch->PS_PatchCode->PC_TaskList)
  339.                         {
  340.                             if( FindTaskListObject( patch, (APTR)tlist->ti_Data, TLI_TYPE_TASKNAME) == NULL)
  341.                             {
  342.                                 if( pointer = ACreateMyListNodeNamed( (struct List *)patch->PS_PatchCode->PC_TaskList, sizeof( struct Node), (STRPTR)tlist->ti_Data))
  343.                                 {
  344.                                     pointer->ln_Type = TLI_TYPE_TASKNAME; /* This must be set, if everything else is initialized ok */
  345.                                 }
  346.                                 else
  347.                                 {
  348.                                     Result = PATERR_OutOfMem;
  349.                                     break;
  350.                                 }
  351.                             }
  352.                         }
  353.                         else
  354.                         {
  355.                             Result = PATERR_NoTaskList;
  356.                             break;
  357.                         }
  358.                         tlist++;
  359.                     }
  360.                     if( Result != PATERR_Ok) goto Ende;
  361.  
  362.  
  363.  
  364.                     tlist = taglist;
  365.                     while( tlist = FindTagItem(PATT_AddTaskPattern, tlist))
  366.                     {
  367.                         if( patch->PS_PatchCode->PC_TaskList)
  368.                         {
  369.                             master = GetMasterPatch( patch);
  370.                             if (DOSBase == (struct DosLibrary *)(master->MPS_PatchedLibraryBase))
  371.                             {
  372.                                 if (master->MPS_PatchedLVO == LVOMatchPattern)
  373.                                 {
  374.                                     Result = PATERR_Restricted;
  375.                                     break;
  376.                                 }
  377.                                 if (master->MPS_PatchedLVO == LVOMatchPatternNoCase)
  378.                                 {
  379.                                     Result = PATERR_Restricted;
  380.                                     break;
  381.                                 }
  382.                             }
  383.                             if( FindTaskListObject( patch, (APTR)tlist->ti_Data, TLI_TYPE_TASKPATTERN) == NULL)
  384.                             {
  385.                                 bufsize = strlen( (STRPTR)tlist->ti_Data) * 2 + 2;
  386.                                 pattern = BAllocmem( bufsize, MEMF_CLEAR | MEMF_PUBLIC);
  387.                                 if( pattern)
  388.                                 {
  389.                                     if( ParsePatternNoCase( (STRPTR)tlist->ti_Data, pattern, bufsize) != -1)
  390.                                     {
  391.                                         if( pointer = ACreateMyListNodeNamed( (struct List *)patch->PS_PatchCode->PC_TaskList, sizeof( struct Node) + 4, (STRPTR)tlist->ti_Data))
  392.                                         {
  393.                                             ((struct TLNode *)pointer)->TN_Pattern = pattern;
  394.                                             pointer->ln_Type = TLI_TYPE_TASKPATTERN; /* This must be set, if everything else is initialized ok */
  395.                                         }
  396.                                         else
  397.                                         {
  398.                                             AFreemem( pattern);
  399.                                             Result = PATERR_OutOfMem;
  400.                                             break;
  401.                                         }
  402.                                     }
  403.                                     else
  404.                                     {
  405.                                         AFreemem( pattern);
  406.                                         Result = PATERR_InvalidPattern;
  407.                                         break;
  408.                                     }
  409.                                 }
  410.                                 else
  411.                                 {
  412.                                     Result = PATERR_OutOfMem;
  413.                                     break;
  414.                                 }
  415.                             }
  416.                         }
  417.                         else
  418.                         {
  419.                             Result = PATERR_NoTaskList;
  420.                             break;
  421.                         }
  422.                         tlist++;
  423.                     }
  424.                     if( Result != PATERR_Ok) goto Ende;
  425.  
  426.  
  427.  
  428.                     tlist = taglist;
  429.                     while( tlist = FindTagItem(PATT_RemTaskID, tlist))
  430.                     {
  431.                         ADeleteMyListNode( FindTaskListObject( patch, (APTR)tlist->ti_Data, TLI_TYPE_TASKID));
  432.                         tlist++;
  433.                     }
  434.  
  435.  
  436.  
  437.                     tlist = taglist;
  438.                     while( tlist = FindTagItem(PATT_RemTaskName, tlist))
  439.                     {
  440.                         pointer = FindTaskListObject( patch, (APTR)tlist->ti_Data, TLI_TYPE_TASKNAME);
  441.                         ADeleteMyListNode( pointer);
  442.                         tlist++;
  443.                     }
  444.  
  445.  
  446.  
  447.                     tlist = taglist;
  448.                     while( tlist = FindTagItem(PATT_RemTaskPattern, tlist))
  449.                     {
  450.                         if( pointer = FindTaskListObject( patch, (APTR)tlist->ti_Data, TLI_TYPE_TASKPATTERN))
  451.                         {
  452.                             AFreemem( ((struct TLNode *)pointer)->TN_Pattern);
  453.                             ADeleteMyListNode( pointer);
  454.                         }
  455.                         tlist++;
  456.                     }
  457.  
  458.  
  459.  
  460.                     tlist = taglist;
  461.                     while( tlist = FindTagItem(PATT_AddRemoveHook, tlist))
  462.                     {
  463.                         AddTail(&(patch->PS_RemoveHookList), (struct Node *)tlist->ti_Data);
  464.                         tlist++;
  465.                     }
  466.  
  467.  
  468.  
  469.                     tlist = taglist;
  470.                     while( tlist = FindTagItem(PATT_RemRemoveHook, tlist))
  471.                     {
  472.                         Remove((struct Node *)tlist->ti_Data);
  473.                         tlist++;
  474.                     }
  475.  
  476.  
  477.  
  478.                     if( tlist = FindTagItem(PATT_UserData, taglist))
  479.                     {
  480.                         patch->PS_UserData = tlist->ti_Data;
  481.                     }
  482.  
  483.  
  484.  
  485.                     if( tlist = FindTagItem(PATT_StackSize, taglist))
  486.                     {
  487.                         master = GetMasterPatch( patch);
  488.                         if ((struct Library *)SysBase == master->MPS_PatchedLibraryBase)
  489.                         {
  490.                             switch( master->MPS_PatchedLVO)
  491.                             {
  492.                                 case LVOStackSwap:
  493.                                 case LVOAllocMem:
  494.                                 case LVOFreeMem:
  495.                                 case LVOFindTask:
  496.                                     Result = PATERR_Restricted;
  497.                                     goto Ende;
  498.                             }
  499.                         }
  500.                         patch->PS_StackSize = tlist->ti_Data;
  501.                         patch->PS_PatchCode->PC_StackSize = tlist->ti_Data;
  502.                         ReCalcStackSize( master);
  503.                     }
  504.  
  505.  
  506.  
  507.                     /* This shouldn't be called, when installing a patch! */
  508.                     if( (patch->PS_Flags & PSF_InternalCall) == 0)
  509.                     {
  510.                         if( tlist = FindTagItem(PATT_Priority, taglist))
  511.                         {
  512.                             if( tlist->ti_Data)
  513.                             {
  514.                                 Disable();
  515.                                 if (TestUsage( patch))
  516.                                 {
  517.                                     Enable();
  518.                                     Result = PATERR_PatchInUse;
  519.                                 }
  520.                                 else
  521.                                 {
  522.                                     patch->PS_Node.ln_Pri = tlist->ti_Data;
  523.                                     master = GetMasterPatch( patch);
  524.                                     Remove( (struct Node *)patch);
  525.                                     Enqueue( (struct List *)&(master->MPS_PatchHeader), (struct Node *)patch);
  526.                                     LinkPatch( master);
  527.                                     CacheClearU();
  528.                                     Enable();
  529.                                 }
  530.                             }
  531.                         }
  532.                     }
  533.                 }
  534.             }
  535.             else
  536.             {
  537.  
  538.  
  539.  
  540.                 master = (struct MasterPatch *)patch;
  541.                 if( tlist = FindTagItem(PATT_Attach, taglist))
  542.                 {
  543.                     master->MPS_PatchedLibraryBase = (struct Library *)tlist->ti_Data;
  544.                     Result = ConnectStartType( master);
  545.                 }
  546.  
  547.  
  548.  
  549.                 if( GetTagData(PATT_Detach, 0L, taglist))
  550.                 {
  551.                     master->MPS_Flags &= ~MPSF_Attached;
  552.                     master->MPS_PatchedLibraryBase = 0L;
  553.                 }
  554.  
  555.  
  556.  
  557.             }
  558. Ende:
  559.             ReleaseSemaphore(&(PatchBase->PB_Semaphore));
  560.  
  561.             if( patch->PS_Node.ln_Type != PS_TYPE_MASTER)
  562.                 if( (Result == PATERR_Ok) && ((patch->PS_Flags & PSF_InternalCall) == 0))
  563.                     SendNotify( PATCOD_PatchChanged, patch);
  564.         }
  565.         if( patch->PS_Node.ln_Type != PS_TYPE_MASTER)
  566.             patch->PS_Flags &= ~PSF_InternalCall;
  567.     }
  568.     return(Result);
  569. }
  570.  
  571. /*--------------------------------------------------------------------------*/
  572. APTR FindTaskListObject( struct Patch *patch, APTR Object, ULONG code)
  573. {
  574. struct Node *pointer;
  575.  
  576.     if( patch->PS_PatchCode->PC_TaskList)
  577.     {
  578.         for (pointer = (struct Node *) patch->PS_PatchCode->PC_TaskList->TL_List.lh_Head;
  579.              pointer->ln_Succ;
  580.              pointer = (struct Node *)pointer->ln_Succ)
  581.         {
  582.             switch( pointer->ln_Type)
  583.             {
  584.                 case TLI_TYPE_TASKID:
  585.                     if (code == TLI_TYPE_TASKID && Object == pointer->ln_Name)
  586.                         return( pointer);
  587.                 case TLI_TYPE_TASKNAME:
  588.                     if (code == TLI_TYPE_TASKNAME && strcmp(pointer->ln_Name, Object) == 0L)
  589.                         return( pointer);
  590.                 case TLI_TYPE_TASKPATTERN:
  591.                     if (code == TLI_TYPE_TASKPATTERN && strcmp(pointer->ln_Name, Object) == 0L)
  592.                         return( pointer);
  593.             }
  594.         }
  595.     }
  596.     return(NULL);
  597. }
  598.